package com.atguigu.gmall.Service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.Service.OrderDetailService;
import com.atguigu.gmall.Service.OrderInfoService;
import com.atguigu.gmall.client.service.CartFeignClientService;
import com.atguigu.gmall.client.service.ProductFeignClientService;
import com.atguigu.gmall.client.service.UserFeignClientService;
import com.atguigu.gmall.constant.MqConst;
import com.atguigu.gmall.entity.CartInfo;
import com.atguigu.gmall.entity.OrderDetail;
import com.atguigu.gmall.entity.OrderInfo;
import com.atguigu.gmall.entity.UserAddress;
import com.atguigu.gmall.enums.OrderStatus;
import com.atguigu.gmall.enums.ProcessStatus;
import com.atguigu.gmall.mapper.OrderInfoMapper;
import com.atguigu.gmall.util.AuthContextHolder;
import com.atguigu.gmall.util.HttpClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Value("${ware_manage.urlPath}")
    private String path;// 远程调用后台的url地址
    @Value("${cancel.order.delay}")
    private Integer cancelOrderDelay;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private UserFeignClientService userFeignClientService;
    @Autowired
    private CartFeignClientService cartFeignClientService;
    @Autowired
    private ProductFeignClientService productFeignClientService;
    @Autowired
    private OrderDetailService orderDetailService;

    @Override
    public Map<String, Object> confirmOrder(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request); //在请求中获取用户id
        //根据用户id获取用户的地址列表
        List<UserAddress> addressList = userFeignClientService.getUserAddressByUserId(userId);
        //获取送货清单
        List<CartInfo> selectedProductList = cartFeignClientService.getSelectedProduct(userId);
        //封装orderDetail
        List<OrderDetail> orderDetailList = this.packageOrderDetail(selectedProductList);
        //计算商品总数量，以及总价格
        BigDecimal totalPrice = new BigDecimal(0);
        Integer totalNumber = 0;
        for (OrderDetail orderDetail : orderDetailList) {
            Integer productNumber = Integer.parseInt(orderDetail.getSkuNum());
            totalPrice =totalPrice.add(orderDetail.getOrderPrice().multiply(new BigDecimal(productNumber))); //计算总金额
            totalNumber += productNumber; //总数量为每个商品的数量相加
        }
        Map<String, Object> retMap = new HashMap<>();
        //获取流水号 防止重复用户无刷新回退提交订单
        String tradeNo = this.getTradeNo(userId);
        retMap.put("tradeNo",tradeNo); //流水号会放入到前端，下次提交请求会携带
        retMap.put("detailArrayList",orderDetailList);
        retMap.put("userAddressList",addressList);
        //totalNum计算方式二
        retMap.put("totalNum",totalNumber);
        //retMap.put("totalNum",totalNum);
        retMap.put("totalMoney",totalPrice);
        return retMap;
    }

    @Override
    public boolean checkTradeNo(String userId,String tradeNo) {
        //从redis中取出检查是否一致
        String tradeNoKey = "user:" + userId + ":tradeNo";
        String tradeNoValue = redisTemplate.opsForValue().get(tradeNoKey).toString();
        if (tradeNo.equals(tradeNoValue))
            return false;//一致返回 false
        return true;
    }

    @Override
    public String getTradeNo(String userId) {
        String tradeNo = UUID.randomUUID().toString();
        //把编号放到reids中
        String tradeNoKey = "user:" + userId + ":tradeNo";
        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    //真实生产环境：当产生价格变动时，是可以提交的订单的，且需要通知用户，而且商家是有权修改价格的
    @Override
    public List<String> checkStockAndPrice(OrderInfo orderInfo, String userId) {
        //创建返回结果
        List<String> resultList = new ArrayList<>();
        //获取用户的订单信息
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //遍历，检查库存以及价格
        if (orderDetailList.isEmpty()){
            resultList.add("未添加任何商品");//如果集合是空的，说明没有商品，直接返回
            return resultList;
        }
        //检查库存
        orderDetailList.stream().forEach(orderDetail -> {
            Long skuId = orderDetail.getSkuId(); //获取skuid
            String skuNum = orderDetail.getSkuNum();
            //发请求，检查 "http://localhost:8100/hasStock?skuId="
//            String retVal = HttpClientUtil.doGet( path+ skuId + "&num=" + skuNum);
            String retVal = "1";// TODO: 2021/9/9 测试使用
            if (retVal.equals("0")) {  //库存不够
                resultList.add("您购买的" +orderDetail.getSkuName()+ "商品库存剩余不足！");
            }
            //检查价格
            BigDecimal realTimePrice = productFeignClientService.getSkuPriceNow(orderDetail.getSkuId());
            if (realTimePrice.compareTo(orderDetail.getOrderPrice()) != 0){
                //如果商品价格发生了变化，即时修改并通知用户，然后修改redis的价格
                resultList.add(orderDetail.getSkuName() + "价格有变动！");
                cartFeignClientService.queryFromDbToRedis(userId);
            }
        });
        return resultList;
    }

    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey = "user:" + userId + ":tradeNo";
        redisTemplate.delete(tradeNoKey);
    }

    @Override
    public Long saveOrderInfoAndDetail(OrderInfo orderInfo) {

        this.setOrderInfoAdditionalValue(orderInfo);
        baseMapper.insert(orderInfo);//主键自增，可以自动回显

        // 保存订单明细
        List<OrderDetail> orderDetailsList = orderInfo.getOrderDetailList();
        if (orderDetailsList.isEmpty()) {
            return null;
        }
        for (OrderDetail orderDetail : orderDetailsList) {
            //此时订单id能拿到吗？ 能 @TableId(type = IdType.AUTO)
            orderDetail.setOrderId(orderInfo.getId());
        }

        //保存订单信息
        orderDetailService.saveBatch(orderDetailsList);
        // TODO: 2021/9/8  超时不付钱,默认30秒就取消订单
/*
        rabbitTemplate.convertAndSend(MqConst.CANCEL_ORDER_EXCHANGE, MqConst.CANCEL_ORDER_ROUTE_KEY, orderInfo.getId(), correlationData -> {
            correlationData.getMessageProperties().setExpiration(cancelOrderDelay);
            return correlationData;
        });
*/
        rabbitTemplate.convertAndSend(MqConst.CANCEL_ORDER_EXCHANGE, MqConst.CANCEL_ORDER_ROUTE_KEY, orderInfo.getId(),
                correlationData->{
                    correlationData.getMessageProperties().setDelay(cancelOrderDelay);
                    return correlationData;
                });
        // TODO: 2021/9/9 订单创建后，删除购物车的商品信息

        return orderInfo.getId();
    }

    @Override
    public void updateOrderStatus(Long id, ProcessStatus processStatus) {
        OrderInfo orderInfo = baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(orderInfo))
            return;
        //更新订单支付状态
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        baseMapper.updateById(orderInfo);
    }

    /*根据订单id查询出订单*/
    @Override
    public OrderInfo findOrderById(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        if (ObjectUtils.isEmpty(orderInfo))
            return null;
        //查询出orderdetail
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        List<OrderDetail> detailList = orderDetailService.list(queryWrapper);
        if (!detailList.isEmpty())
            orderInfo.setOrderDetailList(detailList);
        return orderInfo;
    }

    /*[{"wareHouseId":"1","skuIdList":["18","19"]},{"wareHouseId":"2","skuIdList":["30"]}]*/
    /*订单创建的时候，包括了很多的商品，如果不在同一个仓库，就要进行拆单处理*/
    @Override
    public List<OrderInfo> splitOrder(Long orderId, String wareHouseIdSkuIdJson) {
        //创建返回结果
        ArrayList<OrderInfo> orderInfos = new ArrayList<>();
        //获取原始订单,不包含订单详情
//        OrderInfo originalOrder = this.findOrderById(orderId);
        OrderInfo originalOrder = baseMapper.selectById(orderId);
        //获取订单详情
//        List<OrderDetail> orderDetailList = originalOrder.getOrderDetailList();
        //获取仓库的编号对应sku的id
        List<Map> wareHouseIdSkuIdMapList = JSON.parseArray(wareHouseIdSkuIdJson, Map.class);
        for (Map map : wareHouseIdSkuIdMapList) {
            //创建新的订单,子单，包含了几个仓库就新生成几单
            OrderInfo childOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(originalOrder, childOrderInfo);
            childOrderInfo.setId(null);
            childOrderInfo.setParentOrderId(orderId);//设置母单的id
            String wareHouseId = (String) map.get("wareHouseId");//获取仓库的id
            childOrderInfo.setWareHouseId(wareHouseId);//设置仓库的id
            //获取对应的产品列表
            List<String> skuIdList = (List<String>) map.get("skuIdList");
            //根据skuid和orderid 查出orderDetail信息，封装进新的子单中
            List<OrderDetail> orderDetails = orderDetailService.findOrderDetailBySkus(orderId, skuIdList);
            BigDecimal bigDecimal = new BigDecimal(0);
            for (OrderDetail orderDetail : orderDetails) {
                BigDecimal skuNum = new BigDecimal(orderDetail.getSkuNum());
                bigDecimal = bigDecimal.add(orderDetail.getOrderPrice().multiply(skuNum));
            }
            childOrderInfo.setTotalMoney(bigDecimal);//设置分单后的价格
            childOrderInfo.setOrderDetailList(orderDetails);
            orderInfos.add(childOrderInfo);
        }
        return orderInfos;
    }

    @Override
    public Map<String, Object> assembWareHouseData(OrderInfo orderInfo) {
        //先构造一个map
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderId",orderInfo.getId());
        dataMap.put("consignee",orderInfo.getConsignee());
        dataMap.put("consigneeTel",orderInfo.getConsigneeTel());
        dataMap.put("orderComment",orderInfo.getOrderComment());
        dataMap.put("orderBody",orderInfo.getTradeBody());
        dataMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay",2);
        // 这里要添加一个非常重要的字段
        dataMap.put("wareId",orderInfo.getWareHouseId());
        //商品清单
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //把商品清单放入一个list集合里面
        List<Map> orderDetailMapList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            orderDetailMapList.add(orderDetailMap);
        }
        dataMap.put("details",orderDetailMapList);
        return dataMap;
    }

    /*封装订单详情*/
    private List<OrderDetail> packageOrderDetail(List<CartInfo> selectedProductList) {
        if (selectedProductList.isEmpty())
            return null;
        List<OrderDetail> orderDetails = new ArrayList<>();//创建返回结果
        selectedProductList.stream().forEach(cartInfo->{
            //转换结果
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderPrice(cartInfo.getCartPrice());
            orderDetail.setSkuNum(cartInfo.getSkuNum()+"");
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuId(cartInfo.getSkuId());
            // TODO: 2021/9/7 订单编号
//            orderDetail.setOrderId()
            orderDetails.add(orderDetail);
        });
        return orderDetails;
    }

    /*设置订单额外的属性*/
    private void setOrderInfoAdditionalValue(OrderInfo orderInfo){
        //设置一些页面没有传递过来的值
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());//设置订单的状态
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000); //订单交易编号
        orderInfo.setOutTradeNo(outTradeNo);
        orderInfo.setTradeBody("购物商品信息");
        orderInfo.setCreateTime(new Date());
        //过期时间 默认设置24小时 比如说笔记本库存非常充足的24 ，如果不充足的，那么给30分钟。
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,1);
        orderInfo.setExpireTime(calendar.getTime());
        // 订单的进程状态 {包含订单状态}
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        // TODO: 2021/9/7  还未设置订单的总价，测试使用0.01
        orderInfo.setTotalMoney(new BigDecimal(0.01));

    }

}
